/**
 *    @file       atomic_int.h
 *
 *    @brief      an atomic integer
 *    @details
 *
 *    @version    1.0
 *    @date       12/08/2012 05:57:15 PM
 *
 *    @author     Theophilus, wangtf418@gmail.com
 */
#ifndef _BF_ATOMIC_INT_H_
#define _BF_ATOMIC_INT_H_
#include "comdef.h"

template<typename _Tint>
class atomic_int
{
public:
	atomic_int() : m_int(0)
	{

	}

	atomic_int(_Tint num) : m_int(num)
	{

	}

	virtual ~atomic_int()
	{

	}

public:
	inline _Tint add_return(_Tint add_val)
	{
		return __sync_add_and_fetch(&m_int, add_val);
	}

	inline _Tint sub_return(_Tint sub_val)
	{
		return __sync_sub_and_fetch(&m_int, sub_val);
	}

	inline _Tint or_return(_Tint or_val)
	{
		return __sync_or_and_fetch(&m_int, or_val);
	}

	inline _Tint and_return(_Tint and_val)
	{
		return __sync_and_and_fetch(&m_int, and_val);
	}

	inline _Tint xor_return(_Tint xor_val)
	{
		return __sync_xor_and_fetch(&m_int, xor_val);
	}

	inline _Tint nand_return(_Tint nand_val)
	{
		return __sync_nand_and_fetch(&m_int, nand_val);
	}

	inline _Tint return_add(_Tint add_val)
	{
		return __sync_fetch_and_add (&m_int, add_val);
	}

	inline _Tint return_sub(_Tint sub_val)
	{
		return __sync_fetch_and_sub(&m_int, sub_val);
	}

	inline _Tint return_or(_Tint or_val)
	{
		return __sync_fetch_and_or(&m_int, or_val);
	}

	inline _Tint return_and(_Tint and_val)
	{
		return __sync_fetch_and_and(&m_int, and_val);
	}

	inline _Tint return_xor(_Tint xor_val)
	{
		return __sync_fetch_and_xor(&m_int, xor_val);
	}

	inline _Tint return_nand(_Tint nand_val)
	{
		return __sync_fetch_and_nand(&m_int, nand_val);
	}

	/**
	 * if m_int equal cmp_val, m_int = swap_val and return true, else return flase
	 */
	inline bf_bool_t compare_swap(_Tint cmp_val, _Tint swap_val)
	{
		return __sync_bool_compare_and_swap(&m_int, cmp_val, swap_val);
	}
	/**
	 * if m_int equal cmp_val, m_int = swap_val; 
	 * @return initial value of m_int
	 */
	inline _Tint return_compare_swap(_Tint cmp_val, _Tint swap_val)
	{
		return __sync_val_compare_and_swap(&m_int, cmp_val, swap_val);
	}

	inline void set(_Tint set_val)
	{
		m_int = set_val;
	}
	
	inline _Tint get()
	{
		return m_int;
	}

protected:
	volatile _Tint m_int;
};

typedef atomic_int<bf_int8_t> atomic_int8;
typedef atomic_int<bf_int16_t> atomic_int16;
typedef atomic_int<bf_int32_t> atomic_int32;
typedef atomic_int<bf_int64_t> atomic_int64;

typedef atomic_int<bf_uint8_t> atomic_uint8;
typedef atomic_int<bf_uint16_t> atomic_uint16;
typedef atomic_int<bf_uint32_t> atomic_uint32;
typedef atomic_int<bf_uint64_t> atomic_uint64;

#define atomic_lock_set(lock_ptr, value) __sync_lock_test_and_set(lock_ptr, value)
#define atomic_lock_release(lock_ptr) __sync_lock_release(lock_ptr)
#define atomic_synchronize() __sync_synchronize()

#endif

